﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace JcomTesters.Releases
{
    [jDesc("查找文件或目录,可遍历,可忽略,参数有f,d,full,level等"
        , ok: true, Args = new[] {
            "-debug","debug标识",
            ":d","目录",
            ":f","文件",
            "!d:xxx","排除目录xxx",
            "!f:xxx","排除文件xxx",
            "!:xxx","排除xxx",
            "!xxx","排除xxx",
            "-full","满路径",
            "-l:xxx","满路径",//深度控制 xxx
            "-level:xxx","满路径", //深度控制 xxx
            "xxx","xxx是正则匹配", //内容
        }
        )]
    class FindCmd : Ab1Tester
    {
        public override void Run(string[] args)
        {
            //
            var fiType = 0;//全部
            var exps0 = new List<string>();
            var exps1 = new List<string>();
            var exps2 = new List<string>();
            var patVal = "";
            var full0 = false;
            var level0 = 999999;
            var total_ns = new[] { 0, 0, 0 }; //0 所有文件 1所有目录 2成功匹配
            const int dyn_file = 0;
            const int dyn_dir = 1;
            const int dyn_success = 2;
            foreach (var agitem in args)
            {
                if (agitem.Equals("-debug")) { isDebug = true; }
                else if (agitem.StartsWith(":d", StringComparison.CurrentCultureIgnoreCase)) { fiType = 1; }
                else if (agitem.StartsWith(":f", StringComparison.CurrentCultureIgnoreCase)) { fiType = 2; }
                else if (agitem.StartsWith("!d:", StringComparison.CurrentCultureIgnoreCase)) { exps1.Add(agitem.Substring(3)); }
                else if (agitem.StartsWith("!f:", StringComparison.CurrentCultureIgnoreCase)) { exps2.Add(agitem.Substring(3)); }
                else if (agitem.StartsWith("!:")) { exps0.Add(agitem.Substring(2)); }
                else if (agitem.StartsWith("!")) { exps0.Add(agitem.Substring(1)); }
                else if (agitem.Equals("-full")) { full0 = true; }
                else if (agitem.StartsWith("-l:", StringComparison.CurrentCultureIgnoreCase)) { level0 = int.Parse(agitem.Substring(3)); }
                else if (agitem.StartsWith("-level:", StringComparison.CurrentCultureIgnoreCase)) { level0 = int.Parse(agitem.Substring(7)); }
                else if (agitem.StartsWith("-")) { continue; }
                else { patVal = agitem; }
            }

            var dir1 = System.IO.Directory.GetCurrentDirectory();
            var di = new System.IO.DirectoryInfo(dir1);
            //
            doWhenPatten("workdir: " + dir1 + (dir1.EndsWith("\\") ? "" : "\\"));
            if (true)
            {
                Console.WriteLine("patVal: "+ patVal);
                //Console.WriteLine("fiType: " + fiType);
            }
            Console.WriteLine();
            //
            var dis1 = di.GetDirectories();
            var wlist = new Queue<System.IO.DirectoryInfo>();
            wlist.Enqueue(di);
            //
            var dpTp_N = 1; var dpTp_i = 0;//深度控制-临时变量
            //
            while (wlist.Count > 0)
            {
                //
                var witem = wlist.Dequeue();
                //
                //深度控制
                if (dpTp_i >= dpTp_N) { level0 -= 1; dpTp_N = wlist.Count;dpTp_i = 0; }
                if (level0 < 0) { break; }
                //
                var files = witem.GetFiles();
                foreach (var fitem in files)
                {
                    total_ns[dyn_file]++;
                    //文件
                    var rst0 = ckPatten(2, fitem.Name, patVal, fiType, new[] { exps0, exps1, exps2 }, isDebug);
                    if (rst0 == 0)
                    {
                        total_ns[dyn_success]++;
                        doWhenPatten(full0 ? fitem.FullName : fitem.FullName.Substring(dir1.Length+1));
                    }
                }
                var dirs = witem.GetDirectories();
                foreach (var ditem in dirs)
                {
                    total_ns[dyn_dir]++;
                    //目录
                    var rst0 = ckPatten(1, ditem.Name, patVal, fiType, new[] { exps0, exps1, exps2 }, isDebug);
                    if (rst0 == 2)
                        continue;
                    wlist.Enqueue(ditem);
                    if (rst0 == 0)
                    {
                        total_ns[dyn_success]++;
                        var pt_ph = ditem.FullName + (ditem.FullName.EndsWith("\\") ? "" : "\\");
                        doWhenPatten(full0 ? pt_ph : pt_ph.Substring(dir1.Length+1));
                    }
                }
                //
                //深度控制
                dpTp_i++;
            }
            doWhenPatten("\r\n"+ "total-info files: "+total_ns[dyn_file]+ " dirs: " + total_ns[dyn_dir] + " finds: " + total_ns[dyn_success]);
        }

        //string path = "";
        //if (args.Length > 1) path=args[1];
        //遍历所有文件与子目录,匹配
        //txt
        //
        //Console.WriteLine(
        //    //System.AppDomain.CurrentDomain.BaseDirectory//程序当前目录
        //    System.IO.Directory.GetCurrentDirectory()// 工作目录
        //    );
        //var fnCk=new Func<string,bool>(s=>)

        //过滤，目录，文件，[所有] #暂无链接
        //:d :f [:all]
        //包含
        //【默认】dfe*fjei
        //排除
        //!difn* !aaaa* !node_module*


        //inp_fiType 是 inpName 类型，1目录，2文件，等
        //inpName 是 名称，遍历的(短)文件名或目录名
        //patVal 是 输入的匹配值
        //filter_fiType 是 输入的只过滤的inp_fiType，1目录，2文件，
        //exps 是 输入的 排除 0所有name 1所有目录(也会停止遍历) 2文件
        //返回值 0 匹配成功 1 匹配失败 2不继续遍历
        int ckPatten(int inp_fiType, string inpName, string patVal, int filter_fiType, List<string>[] exps, bool debug0 = false)
        {
            var exps0 = exps[0];
            var exps1 = exps[1];
            var exps2 = exps[2];
            //var debug0 = false;//if(debug0)
            //var debug0 = true;//if(debug0)
            //if (inp_fiType == 1 && !exps0.Where(x => Regex.IsMatch(inpName,x)).Any() && !exps1.Where(x => Regex.IsMatch(inpName, x)).Any())
            var rgIc = RegexOptions.IgnoreCase;

            //if (inpName == "node_modules")
            //{
            //    Console.WriteLine("-node_modules-");
            //    Console.WriteLine(exps0.Where(x => Regex.IsMatch(inpName, x, rgIc)).Any());
            //    Console.WriteLine(exps1.Where(x => Regex.IsMatch(inpName, x, rgIc)).Any());
            //    return 2;
            //}
            if (inp_fiType == 1)
            {
                //排除 目录
                if (exps0.Where(x => Regex.IsMatch(inpName, x, rgIc)).Any() || exps1.Where(x => Regex.IsMatch(inpName, x, rgIc)).Any())
                {
                    if (debug0) Console.WriteLine("return2 2 " + inpName);
                    //Console.WriteLine("return1 2 " + inpName);
                    return 2;
                }
                if (filter_fiType == 2) { if (debug0) Console.WriteLine("return2f 1 " + inpName); return 1; }
                var rst = Regex.IsMatch(inpName, patVal, rgIc) ? 0 : 1;
                if (debug0) Console.WriteLine("return1 " + rst + " " + inpName);
                return rst;
            }
            //排除 文件
            if (inp_fiType == 2 && !exps0.Where(x => Regex.IsMatch(inpName, x, rgIc)).Any() && !exps2.Where(x => Regex.IsMatch(inpName, x, rgIc)).Any()
                //
                && filter_fiType != 1)
            {
                var rst = Regex.IsMatch(inpName, patVal, rgIc) ? 0 : 1;
                if (debug0) Console.WriteLine("return2 " + (rst) + " " + inpName);
                return rst;
            }

            ////不继续遍历的条件: exps了目录
            //if (inp_fiType == 1 && filter_fiType == 2) { if (debug0) Console.WriteLine("return1f 1 " + inpName); return 1; }
            //if (inp_fiType == 2 && filter_fiType == 1) { if (debug0) Console.WriteLine("return2f 1 " + inpName); return 1; }
            if (debug0) Console.WriteLine("return0 1 " + inpName);
            return 1;
        }
        void doWhenPatten(string text)
        {
            Console.WriteLine(text);
        }
    }
}
